package com.qfmy.web.app.service.impl.agent;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.multimodalconversation.AudioParameters;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.qfmy.common.exception.BaseException;
import com.qfmy.common.login.LoginUser;
import com.qfmy.common.login.LoginUserHolder;
import com.qfmy.common.result.ResultCodeEnum;
import com.qfmy.web.app.config.DashScopeConfig;
import com.qfmy.web.app.service.agent.Assistant;
import com.qfmy.web.app.service.agent.ChatService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.FluxSink;


import java.util.*;


/**
 * @author 清风明月
 * @Package com.qfmy.service.impl.assistant
 * @date 2025/5/18
 * @description 智能助手
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class ChatServiceImpl implements ChatService {

    /**
     * 注入阿里的模型配置
     */
    @Autowired
    private DashScopeConfig dashScopeConfig;
    /**
     * 生成器
     */
    private Generation generation;

    /**
     * 注入小时客服
     */
    @Autowired
    private Assistant assistant;

    /**
     * 初始化生成器
     */
    @PostConstruct
    public void init() {
        generation = new Generation();
    }

    /**
     *  服务
     * @param content
     * @return
     */
    @Override
    public String service(String content) {
        String answer = "";
        try {
            GenerationResult result = callQwenModel(content);
            if (result != null && result.getOutput() != null && result.getOutput().getChoices() != null) {
                answer = result.getOutput().getChoices().get(0).getMessage().getContent();
            }
        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            log.error("调用通义千问大模型发生异常", e);
            answer = "抱歉，我暂时无法为您提供回答，请稍后再试。";
        }
        return answer;
    }

    /**
     * 小说客服
     * @param content
     * @return
     */
    @Override
    public String FindNovelService(String content) {
        //获取当前用户信息
        LoginUser loginUser = LoginUserHolder.getLoginUser();
        if(loginUser == null)
        {
            throw new BaseException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        Long userId = loginUser.getUserId();
        //调用
        String answer = assistant.chat(Math.toIntExact(userId), content);
        return answer;
    }



    /**
     * 检查内容
     * @param content
     */
    @Override
    public void checkByAi(String content) {
        // 提示语
        String prompt = "请严格检测以下内容是否存在敏感信息（含违法、违规、低俗内容）：\n";
        prompt += "【检测规则】仅返回true（存在敏感信息）或false（不存在敏感信息），无需任何额外说明、解释或多余文本！\n";
        prompt += "【待检测内容】" + content;
        try {
            Generation gen = new Generation();
            Message userMsg = Message.builder()
                    .role(Role.USER.getValue())
                    .content(prompt)
                    .build();
            GenerationParam param = GenerationParam.builder()
                    .apiKey(dashScopeConfig.getApiKey())
                    .model(dashScopeConfig.getCustomerservice())
                    .messages(Arrays.asList(userMsg))
                    .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                    .build();
            GenerationResult call = gen.call(param);
            if (call != null && call.getOutput() != null && call.getOutput().getChoices() != null) {
               String result = call.getOutput().getChoices().get(0).getMessage().getContent();
               // 判断结果
               if(result.equals("true"))
               {
                   throw new BaseException(ResultCodeEnum.APP_ILLEGAL_CONTENT);
               }
            }
        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            log.error("调用通义千问大模型发生异常", e);
            throw new BaseException(ResultCodeEnum.SERVICE_ERROR);
        }
    }

    /**
     * 文本转语音（固定中文语种，使用qwen3-tts-flash模型）
     * @param text 待转换的中文文本
     * @return 音频资源URL
     */
    public String tts(String text) {
        MultiModalConversation conv = new MultiModalConversation();

        // 构建参数
        MultiModalConversationParam param = MultiModalConversationParam.builder()
                .model(dashScopeConfig.getModelTts())
                .apiKey(dashScopeConfig.getApiKey())
                .text(text)
                .voice(AudioParameters.Voice.CHERRY)
                .build();

        try {
            // 非流式调用，获取音频URL
            MultiModalConversationResult result = conv.call(param);
            return result.getOutput().getAudio().getUrl();
        }catch (Exception e)
        {
            log.error("调用通义千问大模型发生异常", e);
            throw new BaseException(ResultCodeEnum.SERVICE_ERROR);
        }
    }



    /**
     * 调用通义千问大模型获取回答
     * @param content 用户问题内容
     * @return 模型返回的结果
     * @throws ApiException           当API调用发生错误时
     * @throws NoApiKeyException      当未配置API密钥时
     * @throws InputRequiredException 当输入内容为空时
     */
    @NotNull
    private GenerationResult callQwenModel(String content) throws ApiException, NoApiKeyException, InputRequiredException {
        Generation gen = new Generation();
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("你是一个智能客服")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content(content)
                .build();
        GenerationParam param = GenerationParam.builder()
                .apiKey(dashScopeConfig.getApiKey())
                .model(dashScopeConfig.getCustomerservice())
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .build();
        GenerationResult call = gen.call(param);
        return call;
    }


    /**
     * 构建多模态对话参数
     *
     * @param userMessage
     * @return
     */
    private MultiModalConversationParam buildMultiModalConversationParam(MultiModalMessage message) {
        return MultiModalConversationParam.builder()
                .apiKey(dashScopeConfig.getApiKey())
                .model(dashScopeConfig.getModelImageInstruct())
                .messages(Collections.singletonList(message))
                .incrementalOutput(true)
                .build();
    }



    /**
     * 处理生成器返回的结果
     *
     * @param result
     * @param emitter
     * @param aiResponseBuilder
     */
    private void processResult(GenerationResult result, FluxSink<String> emitter, StringBuilder aiResponseBuilder) {
        try {
            String content = result.getOutput()
                    .getChoices()
                    .get(0)
                    .getMessage()
                    .getContent();

            if (content != null && !content.isEmpty()) {
                aiResponseBuilder.append(content);
                emitter.next(content);
            }
        } catch (Exception e) {
            emitter.error(new RuntimeException("解析响应失败: " + e.getMessage()));
        }
    }

    /**
     * 获取用户id
     *
     * @return
     */
    @Nullable
    @Contract(pure = true)
    private Long getUserId() {
        LoginUser loginUser = LoginUserHolder.getLoginUser();
        if (loginUser == null) {
            throw new BaseException(ResultCodeEnum.TOKEN_INVALID);
        }
        return loginUser.getUserId();
    }
}